package com.tfswx.jkgl.core.utils;

import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ricky
 * @date 2021/12/27
 */
public class MyScriptEngine {
    private final ScriptEngine engine;

    public MyScriptEngine() {
        this(null);
    }

    @SneakyThrows
    public MyScriptEngine(String jsName) {
        engine = new ScriptEngineManager().getEngineByName("js");
        if (StringUtils.isNotBlank(jsName)) {
            File file = ResourceUtils.getFile("classpath:js/" + jsName + ".js");
            engine.eval(new FileReader(file));
        }
    }

    @SneakyThrows
    public Object eval(String bdsStr) {
        return engine.eval(bdsStr);
    }

    public void put(String key, Object value) {
        engine.put(key, value);
    }

    @SneakyThrows
    public Object eval(String bdsStr, Object param) {
        if (param == null) {
            return eval(bdsStr);
        }
        Map<String, Object> stringObjectMap = new HashMap<>();
        if (param instanceof List) {
            stringObjectMap.put("list", param);
            String[] split = bdsStr.split("\\+");
            for (int j = 0; j < split.length; j++) {
                String s = split[j];
                split[j] = "list" + s.trim();
            }
            bdsStr = String.join("+", split);
        } else {
            stringObjectMap.put("obj", param);
            String[] split = bdsStr.split("\\+");
            for (int j = 0; j < split.length; j++) {
                String s = split[j];
                split[j] = "obj." + s.trim();
            }
            bdsStr = String.join("+", split);
        }
        ScriptContext context = engine.getContext();
        Bindings bindings = engine.createBindings();
        for (Integer scope : context.getScopes()) {
            Bindings bindings1 = context.getBindings(scope);
            bindings.putAll(bindings1);
        }

        bindings.putAll(stringObjectMap);
        return engine.eval(bdsStr, bindings);
    }

    public static void main(String[] args) {
        MyScriptEngine myScriptEngine = new MyScriptEngine();
        List<Object> objects = new ArrayList<>();
        Map<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("old", "ok");
        objects.add(objectObjectHashMap);
        Object eval = myScriptEngine.eval("[0].old='nook'", objects);
        System.out.println(eval);
        System.out.println(objects);
    }
}
